/*! \file routines.cpp
 *	\brief 
 *
 *	created:	2009/11/23
 *	created:	23:11:2009   16:22
 *	filename: 	o:\gag-engine\libs\mem\impl\routines.cpp
 *	file path:	o:\gag-engine\libs\mem\impl
 *	file base:	routines
 *	file ext:	cpp
 *	author:		Vitalii Trubchaninov
 *				venngraydog@gmail.com
 */

#include "mem/stdafx.h"
#include "mem/impl/routines.h"

#if TT_MEM_ENABLED

#include <tbb/scalable_allocator.h>

#include <core/assert.h>

#if TT_MEM_PROFILING
#	include "block_header.h"
#	include "provider.h"
#endif //TT_MEM_PROFILING

namespace tt{
namespace mem{
namespace impl{

//////////////////////////////////////////////////////////////////////////
MEM_API void* mgt_malloc( std::size_t size )
{
	return scalable_malloc(size);
}

MEM_API void mgt_free( void* p )
{
	scalable_free(p);
}

//////////////////////////////////////////////////////////////////////////
#if TT_MEM_PROFILING

MEM_API bool g_my_mem_function = false;

MEM_API void* mgt_new( std::size_t size )
{
	g_my_mem_function = true;
	impl::BlockHeader* block = impl::block_new<impl::BT_ONE>(size);
	block->section = impl::g_provider().register_new(size);
	g_my_mem_function = false;
	return impl::to_memory(block);
}

MEM_API void* mgt_new_array( std::size_t size )
{
	g_my_mem_function = true;
	impl::BlockHeader* block = impl::block_new<impl::BT_ARRAY>(size);
	block->section = impl::g_provider().register_new_array(size);
	g_my_mem_function = false;
	return impl::to_memory(block);
}

MEM_API void* mgt_new( void* mem_section, std::size_t size )
{
	impl::BlockInfo* block_section = reinterpret_cast<impl::BlockInfo*>(mem_section);
	g_my_mem_function = true;
	impl::BlockHeader* block = impl::block_new<impl::BT_ONE>(size);
	block->section = block_section;
	impl::g_provider().register_new(block_section, size);
	g_my_mem_function = false;
	return impl::to_memory(block);
}

MEM_API void* mgt_new_array( void* mem_section, std::size_t size )
{
	impl::BlockInfo* block_section = reinterpret_cast<impl::BlockInfo*>(mem_section);
	g_my_mem_function = true;
	impl::BlockHeader* block = impl::block_new<impl::BT_ARRAY>(size);
	block->section = block_section;
	impl::g_provider().register_new_array(block_section, size);
	g_my_mem_function = false;
	return impl::to_memory(block);
}

MEM_API void mgt_delete( void* p )
{
	if (!p)
		return;

	impl::BlockHeader* block = impl::to_block_header(p);
	impl::g_provider().register_delete(block->section, block->size);
	impl::block_delete<impl::BT_ONE>(block);
}

MEM_API void mgt_delete_array( void* p )
{
	if (!p)
		return;

	impl::BlockHeader* block = impl::to_block_header(p);
	impl::g_provider().register_delete_array(block->section, block->size);
	impl::block_delete<impl::BT_ARRAY>(block);
}

MEM_API std::size_t mgt_size( void* p )
{
	impl::BlockHeader* block = impl::to_block_header(p);
	return block->size;
}

#else //TT_MEM_PROFILING

MEM_API void* mgt_new( std::size_t size )
{
	return mgt_malloc(size);
}

MEM_API void* mgt_new_array( std::size_t size )
{
	return mgt_malloc(size);
}

MEM_API void mgt_delete( void* p )
{
	return mgt_free(p);
}

MEM_API void mgt_delete_array( void* p )
{
	return mgt_free(p);
}

MEM_API unsigned int mgt_size( void* /*p*/ )
{
	TT_NOT_IMPLEMENTED("mgt_size");
}

#endif //TT_MEM_PROFILING

} //namespace impl
} //namespace mem
} //namespace tt

#endif //TT_MEM_ENABLED
